package com.nineclock.approve.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.nineclock.approve.dto.*;
import com.nineclock.approve.mapper.ApproveDefinitionMapper;
import com.nineclock.approve.pojo.ApproveDefinition;
import com.nineclock.approve.service.ActivitiService;
import com.nineclock.approve.service.ApproveDefinitionService;
import com.nineclock.approve.utils.ApproveExtendsUtils;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NCException;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.common.utils.CurrentUserHolder;
import com.nineclock.common.utils.JsonUtils;
import com.nineclock.common.utils.UUIDUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional
public class ApproveDefinitionServiceImpl implements ApproveDefinitionService {
    @Autowired
    ApproveDefinitionMapper approveDefinitionMapper;
    @Autowired
    ActivitiService activitiService;
    /**
     * 查询审批列表并进行分组
     *
     * @return
     */
    @Override
    public List<ApproveGroupDefinitionDto> queryDefinitionGroup() {

        Long companyId = CurrentUserHolder.get().getCompanyId();
        // 根据公司ID和有效标识组装查询条件
        LambdaQueryWrapper<ApproveDefinition> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ApproveDefinition::getCompanyId, companyId);
        queryWrapper.eq(ApproveDefinition::getIsValid, 1);
        List<ApproveDefinition> approveDefinitions = approveDefinitionMapper.selectList(queryWrapper);
        List<ApproveGroupDefinitionDto> result = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(approveDefinitions)) {
            // 将数据按照分类进行分组
            Map<String, List<ApproveDefinition>> groupResult = approveDefinitions.stream().collect(Collectors.groupingBy(ApproveDefinition::getGroupType));
            // 遍历组装数据
            for (String groupType : groupResult.keySet()) {
                // 组装数据
                ApproveGroupDefinitionDto approveGroupDefinitionDto = new ApproveGroupDefinitionDto();
                approveGroupDefinitionDto.setGroupType(groupType);
                approveGroupDefinitionDto.setDefinitionList(groupResult.get(groupType));
                result.add(approveGroupDefinitionDto);
            }
        }
        // 返回
        return result;
    }

    /**
     * 新增/修改
     * @param approveDefinitionSaveDto
     */
    @Override
    public void saveApproveDefinition(ApproveDefinitionSaveDto approveDefinitionSaveDto) {
        // 参数校验
        if (approveDefinitionSaveDto == null || approveDefinitionSaveDto.getBaseData() == null || approveDefinitionSaveDto.getTableData() == null || StrUtil.isEmpty(approveDefinitionSaveDto.getFlowData())) {
            throw new NCException(ResponseEnum.MESSAGE_PARAMS_LOST);
        }
        // 根据主键决定是创建还是修改,如果主键不存在则是创建,存在则是修改
            //创建 ==  获取数据
        ApproveDefinition approveDefinition = BeanHelper.copyProperties(approveDefinitionSaveDto.getBaseData(), ApproveDefinition.class);
        if (StrUtil.isEmpty(approveDefinition.getId())) {
            // 封装基本信息
            approveDefinition.setCompanyId(CurrentUserHolder.get().getCompanyId() + "");
            approveDefinition.setCreateTime(new Date());
            approveDefinition.setUpdateTime(new Date());
            approveDefinition.setIsValid("1");
            approveDefinition.setDataFrom("1");// 默认
            // 将前端传来的谁可以发起审批的字段集合 转为json存入数据库中
            List<AllowUserObjDto> allowUserJsonList = approveDefinitionSaveDto.getBaseData().getAllowUserJson();
            approveDefinition.setAllowUserJson(JsonUtils.toString(allowUserJsonList));
            // 封装表单信息
            List<ApproveDefinitionTableDataDto> tableDataList = approveDefinitionSaveDto.getTableData();
            approveDefinition.setFormJson(JsonUtils.toString(tableDataList));
            // 扩充表单信息 增加columns这一列数据 filed-key
            List<ColumnObjDto> fieldKeys = ApproveExtendsUtils.getClolumnListWithFieldKey(approveDefinitionSaveDto);
            approveDefinition.setColumns(JsonUtils.toString(fieldKeys));
            // 设置tablename
            approveDefinition.setTableName("flow_" + UUIDUtils.getUUID());
            // 设置流程信息
            //为了后续使用, 每一个节点都需要扩充一个唯一标识 nodeKey ;
            String flowData = approveDefinitionSaveDto.getFlowData();
            cn.hutool.json.JSONArray jsonArray = JSONUtil.parseArray(flowData);
            ApproveExtendsUtils.expandParamWithNodeKey(jsonArray);
            approveDefinition.setFlowJson(JSONUtil.toJsonStr(jsonArray));
            // 插入数据库
            approveDefinitionMapper.insert(approveDefinition);
            //TODO 添加的时候 ,部署流程到Activiti中
            activitiService.deployProcessToActiviti(approveDefinition);
        } else {
            // 修改
            // 根据ID查询信息
            ApproveDefinition approveDefinitionUpdate= approveDefinitionMapper.selectById(approveDefinition.getId());
            // 为基本信息赋值
            BeanUtils.copyProperties(approveDefinition, approveDefinitionUpdate);
            //ApproveDefinition approveDefinitionUpdate = BeanHelper.copyProperties(approveDefinition1, ApproveDefinition.class);
            // 将前端传来的谁可以发起审批的字段集合 转为json存入数据库中
            List<AllowUserObjDto> allowUserJsonList = approveDefinitionSaveDto.getBaseData().getAllowUserJson();

            approveDefinitionUpdate.setAllowUserJson(JsonUtils.toString(allowUserJsonList));
            // 封装表单信息
            List<ApproveDefinitionTableDataDto> tableDataList = approveDefinitionSaveDto.getTableData();
            approveDefinitionUpdate.setFormJson(JsonUtils.toString(tableDataList));
            // 扩充表单信息 增加columns这一列数据 filed-key
            List<ColumnObjDto> fieldKeys = ApproveExtendsUtils.getClolumnListWithFieldKey(approveDefinitionSaveDto);
            approveDefinitionUpdate.setColumns(JsonUtils.toString(fieldKeys));
            // 设置tablename
            approveDefinitionUpdate.setTableName("flow_" + UUIDUtils.getUUID());
            // 设置流程信息
            //为了后续使用, 每一个节点都需要扩充一个唯一标识 nodeKey ;
            String flowData = approveDefinitionSaveDto.getFlowData();
            cn.hutool.json.JSONArray jsonArray = JSONUtil.parseArray(flowData);
            ApproveExtendsUtils.expandParamWithNodeKey(jsonArray);
            approveDefinitionUpdate.setFlowJson(JSONUtil.toJsonStr(jsonArray));
                // 更新数据库
            approveDefinitionMapper.updateById(approveDefinitionUpdate);
            // TODO 修改的时候,部署到Activiti中
            // 在修改审批流程完毕后, 需要删除原来的流程实例, 部署新的流程实例
            activitiService.deleteProcessDefinition(approveDefinitionUpdate.getId());
            activitiService.deployProcessToActiviti(approveDefinitionUpdate);

        }

    }

    /**
     * 根据ID查询回显数据
     *
     * @param id
     * @return
     */
    @Override
    public ApproveDefinitionResultDto queryDefinitionById(String id) {
        ApproveDefinitionResultDto resultDto = new ApproveDefinitionResultDto();
        ApproveDefinition approveDefinition = approveDefinitionMapper.selectById(id);
        if (approveDefinition != null) {
            // 封装基础信息
            ApproveDefinitionBaseDataDto approveDefinitionBaseDataDto = BeanHelper.copyProperties(approveDefinition, ApproveDefinitionBaseDataDto.class);
            List<AllowUserObjDto> allowUserObjDtos = JsonUtils.toList(approveDefinition.getAllowUserJson(), AllowUserObjDto.class);
            approveDefinitionBaseDataDto.setAllowUserJson(allowUserObjDtos);
            resultDto.setBaseData(approveDefinitionBaseDataDto);
            // 封装表单数据
            String formJson = approveDefinition.getFormJson();
            List<ApproveDefinitionTableDataResultDto> tableList = JsonUtils.toList(formJson, ApproveDefinitionTableDataResultDto.class);
            resultDto.setTableData(tableList);
            // 封装流程信息
            resultDto.setFlowData(approveDefinition.getFlowJson());
            return resultDto;
        }
        return null;
    }
}
